import type { BasicColumn, BasicTableProps, CellFormat, GetColumnsParams } from '../types/table';
import type { PaginationProps } from '../types/pagination';
import type { ComputedRef, Ref } from 'vue';
import { computed, ref, reactive, toRaw, unref, watch, h } from 'vue';

import { isArray, isBoolean, isFunction, isMap, isNumber, isString } from '@/utils/is';
import { cloneDeep, isEqual } from 'lodash-es';
import { formatToDate, timestampToTime, timestampToDate, timestampToMonth } from '@/utils/dateUtil';
import { ACTION_COLUMN_FLAG, DEFAULT_ALIGN, INDEX_COLUMN_FLAG, PAGE_SIZE } from '../const';
import { Tag, Badge } from 'ant-design-vue';

import TableImg from '@/components/table/src/components/TableImg.vue';

import useMediaQuery from '@/hooks/web/useMediaQuery';
const colSize = useMediaQuery();
const isMobileCol = computed(() => colSize.value === 'sm' || colSize.value === 'xs');

function handleItem(item: BasicColumn) {
  const { children } = item;
  item.align = item.align || DEFAULT_ALIGN;
  if (children && children.length) {
    handleChildren(children);
  }
  handleDataFormat(item);
}

//处理列数据格式化
function handleDataFormat(item: BasicColumn){
  const { customRender,dataFormat } = item;
  //如果已定义或没定义
  if(customRender || !dataFormat){
    return;
  }
  switch (dataFormat.type) {
    case 'badge':formatBadge(item);break;
    case 'datemonth': formatDateMonth(item);break;
    case 'datetime':formatDateTime(item);break;
    case 'date':formatDate(item);break;
    case 'text':formatText(item);break;
    case 'tag':formatTag(item);break;
    case 'radix':formatRadix(item);break;
    case 'img':formatImg(item);break;
    default:break;
  }
}

//徽标点
const formatBadge = (item: BasicColumn) =>{
  const { options = [] }:any = item.dataFormat;
  item.customRender = ({ text }) =>{
    const find = options.find((item: any) => item.value === text);
    if(find){
      return h(Badge,{ text:find.label, color:find.color });
    }
    return '';
  };
};

// 时间戳格式化月份
const formatDateMonth = (item: BasicColumn) =>{
  item.customRender = ({ text }) =>{
    if(text>0) {
      return timestampToMonth(text);
    }
    return '';
  };
};
// 时间戳格式化日期
const formatDate = (item: BasicColumn) =>{
  item.customRender = ({ text }) =>{
    if(text>0) {
      return timestampToDate(text);
    }
    return '';
  };
};

// 时间戳格式化时间
const formatDateTime = (item: BasicColumn) =>{
  item.customRender = ({ text }) =>{
    if(text>0) {
      return timestampToTime(text);
    }
    return '';
  };
};

//处理文本
const formatText = (item: BasicColumn) =>{
  const { options = [] }:any = item.dataFormat;
  item.customRender = ({ text }) =>{
    const find = options.find((item:any) => item.value === text);
    if(find){
      return h('span',{ style:{ color:find.color } },find.label);
    }
    return '';
  };
};

//格式化tag
const formatTag = (item:BasicColumn) =>{
  const { options = [] }:any = item.dataFormat;
  item.customRender = ({ text }) =>{
    const find = options.find((item: any) => item.value === text);
    if(find){
      return h(Tag,{ color:find.color, class: 'cell-tag' },()=>find.label);
    }
    return '';
  };
};

// 格式化小数点
const formatRadix = (item:BasicColumn) => {
  const { toFixed=undefined }:any = item['dataFormat'];
  item.customRender = ({ text }) =>{
    if(!isNaN(text) && toFixed){
      if(!isNumber(text)){
        return (parseFloat(text)).toFixed(toFixed);
      }else{
        return (text).toFixed(toFixed);
      }
    }
    return text;
  };
  return '';
};

// 处理图片功能
const formatImg = (item:BasicColumn) => {
  const { size=40 }:any = item['dataFormat'];
  item.customRender = ({ text }) =>{
    if(text){
      return h(TableImg,{ size: size, imgList: [text], simpleShow: true });
    }
    return '';
  };
};

function handleChildren(children: BasicColumn[] | undefined) {
  if (!children) return;
  children.forEach((item) => {
    const { children } = item;
    handleItem(item);
    handleChildren(children);
  });
}

function handleIndexColumn(
  propsRef: ComputedRef<BasicTableProps>,
  getPaginationRef: ComputedRef<boolean | PaginationProps>,
  columns: BasicColumn[],
) {

  const { showIndexColumn, indexColumnProps, isTreeTable } = unref(propsRef);

  let pushIndexColumns = false;
  if (unref(isTreeTable)) {
    return;
  }
  columns.forEach(() => {
    const indIndex = columns.findIndex((column) => column.flag === INDEX_COLUMN_FLAG);
    if (showIndexColumn) {
      pushIndexColumns = indIndex === -1;
    } else if (!showIndexColumn && indIndex !== -1) {
      columns.splice(indIndex, 1);
    }
  });

  if (!pushIndexColumns) return;

  const isFixedLeft = columns.some((item) => item.fixed === 'left');

  columns.unshift({
    flag: INDEX_COLUMN_FLAG,
    width: 56, //序号宽度
    title: '序号',
    align: 'center',
    customRender: ({ index }) => {
      const getPagination = unref(getPaginationRef);
      if (isBoolean(getPagination)) {
        return `${index + 1}`;
      }
      const { current = 1, pageSize = PAGE_SIZE } = getPagination;
      return ((current < 1 ? 1 : current) - 1) * pageSize + index + 1;
    },
    ...(isFixedLeft
      ? {
          fixed: 'left',
        }
      : {}),
    ...indexColumnProps,
  });
}

function handleActionColumn(propsRef: ComputedRef<BasicTableProps>, columns: BasicColumn[]) {
  const { actionColumns } = unref(propsRef);
  if (!actionColumns || !actionColumns.length) return;

  const hasIndex = columns.findIndex((column) => column.flag === ACTION_COLUMN_FLAG);
  if (hasIndex === -1) {
    actionColumns.forEach((actColumn) => {
      columns.push({
        ...columns[hasIndex],
        fixed: isMobileCol.value ? false : 'right',
        width: 'auto',
        ...actColumn,
        flag: ACTION_COLUMN_FLAG,
      });
    })
  }
}

export function useColumns(
  propsRef: ComputedRef<BasicTableProps>,
  getPaginationRef: ComputedRef<boolean | PaginationProps>,
  tableData: Recordable<any>,
) {
  const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>;
  let cacheColumns = unref(propsRef).columns;

  const getColumnsRef = computed(() => {
    const columns = cloneDeep(unref(columnsRef));

    handleIndexColumn(propsRef, getPaginationRef, columns);
    handleActionColumn(propsRef, columns);
    if (!columns) {
      return [];
    }

    columns.forEach((item) => {
      handleItem(item);
    });
    return columns;
  });

  function isIfShow(column: BasicColumn): boolean {
    const ifShow = column.ifShow;

    let isIfShow = true;

    if (isBoolean(ifShow)) {
      isIfShow = ifShow;
    }
    if (isFunction(ifShow)) {
      isIfShow = ifShow(column);
    }
    return isIfShow;
  }

  const getViewColumns = computed(() => {
    const viewColumns = sortFixedColumn(unref(getColumnsRef));

    const columns = cloneDeep(viewColumns);
    return columns
      .filter((column) => {
        return isIfShow(column);
      })
      .map((column) => {
        const { slots, customRender, format, flag } = column;

        if (!slots || !slots?.title) {
          // column.slots = { title: `header-${dataIndex}`, ...(slots || {}) };
          column.customTitle = column.title as any;
          Reflect.deleteProperty(column, 'title');
        }
        const isDefaultAction = [INDEX_COLUMN_FLAG, ACTION_COLUMN_FLAG].includes(flag!);
        if (!customRender && format && !isDefaultAction) {
          column.customRender = ({ text, record, index }) => {
            return formatCell(text, format, record, index);
          };
        }

        setDefaultWidth(column); // 设置列默认宽度


        return reactive(column);
      });
  });

  // 设置列默认宽度...
  // 如未设置width，先处理dataFormat>type日期时间格式字段，其他按默认宽度设置
  function setDefaultWidth(column:BasicColumn):void{

    // console.log('column.width1='+column.width);
    if(!Reflect.has(column,'width')){
      // 处理dataFormat>type日期时间格式字段
      const { dataFormat } = column;
      if (dataFormat) {
        const { type } = dataFormat;
        if (type==='datetime') { //日期时间
          column.width = !isMobileCol.value ? 140 : 154; //>140,ios>=154
        }else if(type==='date') { //日期
          column.width = !isMobileCol.value ? 85 : 94;
        }else if(type==='datemonth') { //年月:2023-06
          column.width = !isMobileCol.value ? 70 : 80;
        }else{
          column.width = 104;
        }
      }else{ // 其他列默认宽度
        column.width = 104;
      }
    }
    // console.log('column.width2='+column.width+'\n\n');
  }

  watch(
    () => unref(propsRef).columns,
    (columns) => {
      columnsRef.value = columns;
      cacheColumns = columns?.filter((item) => !item.flag) ?? [];
    },
  );

  function setCacheColumnsByField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
    if (!dataIndex || !value) {
      return;
    }
    cacheColumns.forEach((item) => {
      if (item.dataIndex === dataIndex) {
        Object.assign(item, value);
        return;
      }
    });
  }
  /**
   * set columns
   * @param columnList key｜column
   */
  function setColumns(columnList: Partial<BasicColumn>[] | (string | string[])[]) {
    const columns = cloneDeep(columnList);
    if (!isArray(columns)) return;

    if (columns.length <= 0) {
      columnsRef.value = [];
      return;
    }

    const firstColumn = columns[0];

    const cacheKeys = cacheColumns.map((item) => item.dataIndex);

    if (!isString(firstColumn) && !isArray(firstColumn)) {
      columnsRef.value = columns as BasicColumn[];
    } else {
      const columnKeys = (columns as (string | string[])[]).map((m) => m.toString());
      const newColumns: BasicColumn[] = [];
      cacheColumns.forEach((item) => {
        newColumns.push({
          ...item,
          defaultHidden: !columnKeys.includes(item.dataIndex?.toString() || (item.key as string)),
        });
      });
      // Sort according to another array
      if (!isEqual(cacheKeys, columns)) {
        newColumns.sort((prev, next) => {
          return (
            columnKeys.indexOf(prev.dataIndex?.toString() as string) -
            columnKeys.indexOf(next.dataIndex?.toString() as string)
          );
        });
      }
      columnsRef.value = newColumns;
    }
  }

  function getColumns(opt?: GetColumnsParams) {
    const { ignoreIndex, ignoreAction, sort } = opt || {};
    let columns = toRaw(unref(getColumnsRef));
    if (ignoreIndex) {
      columns = columns.filter((item) => item.flag !== INDEX_COLUMN_FLAG);
    }
    if (ignoreAction) {
      columns = columns.filter((item) => item.flag !== ACTION_COLUMN_FLAG);
    }

    if (sort) {
      columns = sortFixedColumn(columns);
    }

    return columns;
  }
  function getCacheColumns() {
    return cacheColumns;
  }

  return {
    getColumnsRef,
    getCacheColumns,
    getColumns,
    setColumns,
    getViewColumns,
    setCacheColumnsByField,
  };
}

function sortFixedColumn(columns: BasicColumn[]) {
  const fixedLeftColumns: BasicColumn[] = [];
  const fixedRightColumns: BasicColumn[] = [];
  const defColumns: BasicColumn[] = [];
  for (const column of columns) {
    if (column.fixed === 'left') {
      fixedLeftColumns.push(column);
      continue;
    }
    if (column.fixed === 'right') {
      fixedRightColumns.push(column);
      continue;
    }
    defColumns.push(column);
  }
  return [...fixedLeftColumns, ...defColumns, ...fixedRightColumns].filter(
    (item) => !item.defaultHidden,
  );
}

// format cell
export function formatCell(text: any, format: CellFormat, record: Recordable, index: number) {
  if (!format) {
    return text;
  }

  // custom function
  if (isFunction(format)) {
    return format(text, record, index);
  }

  try {
    // date type
    const DATE_FORMAT_PREFIX = 'date|';
    if (isString(format) && format.startsWith(DATE_FORMAT_PREFIX) && text) {
      const dateFormat = format.replace(DATE_FORMAT_PREFIX, '');

      if (!dateFormat) {
        return text;
      }
      return formatToDate(text, dateFormat);
    }

    // Map
    if (isMap(format)) {
      return format.get(text);
    }
  } catch (error) {
    return text;
  }
}
